{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Code to measure Entangling capacity of any Parameterized Quantum Circuit"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Sim et.al. in [1] proposed three metrics to represent Ansatz quality of variational circuits namely: Expressibility, Entangling capacity and circuit cost. This notebook implements the Entangling capacity metric that is very useful for any parameterized quantum circuit (or ansatz) for any variational quantum algorithm. While for some domain like physics or chemistry, there are domain-inspired ansatzes, for all other applications the choice of circuits is heuristic-based. With metrics like entangling capacity we can do correlation studies between such metrics and accuracy or precision-recall of an application and accordingly choose an ansatz for the variational algorithm in consideration for that application.\n",
    "\n",
    "In this notebook we have implemented these metrics and matched our numbers to that of this paper. We have two ways to compute Entangling capacity -using Meyer Wallach measure (as proposed in the paper[1]) and Von-Neumann measure."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "from qiskit.quantum_info import partial_trace, Statevector\n",
    "from parametric_circuits import Ansatz\n",
    "from qiskit import QuantumCircuit\n",
    "import qiskit.quantum_info as qi\n",
    "from qiskit import transpile\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The following cell implements entangling capacity using meyer-wallach measure for a statevector. It expects as input the statevector of $n$ qubits and the total number of qubits $n$ for calculating the the entangling capacity of a particular statevector using Meyer Wallach Measure.\n",
    "Meyer Wallach measure (this measure is also know as average bipartite entanglement measurement) and is defined by \n",
    "$\n",
    "\\begin{equation}\n",
    "    \\mathcal{Q}(|\\psi\\rangle) = 2 - \\frac{2}{n}\\sum_{i =1}^{n}Tr(\\rho_i^2)\n",
    "\\end{equation}\n",
    "$\n",
    "The above equation is the entanglement measurement over just one statevector of the system to get the entangling capability of a parameteric quantum circuit as given in paper[1], we sample over several iteration with different random parameters for the parametric gates and average it to the get the expectation of the entangling capability of the circuit with respect to Meyer - Wallach Measure.\n",
    "The key properties of using Meyer Wallach measure to calculate entangling capacity metric :\n",
    "\n",
    " 1. The value $\\mathcal{Q}$ is invariant under local unitaries.\n",
    " 2. It assumes it values between the range $0 \\ge \\mathcal{Q} \\le 1 $.\n",
    " 3. $\\mathcal{Q}(|\\psi\\rangle) = 0$ if and only if $|\\psi\\rangle$ is a product state.\n",
    "\n",
    " The Meyer-Wallach Measure find its application in quantum information processing due to following advantages:\n",
    " 1. Due to its nature its a average linear entropy over reduced qubits state i.e. $\\mathcal{Q} = \\{1 - tr\\{\\rho^2\\}\\}$, making it a standard measure over different applications and easy to compare  and comprehend values due to its linear scaling.\n",
    " 2. The Meyer-Wallach Measure can be applied as a tool for tracking convergence of pseudo-random circuit by comparing the Meyer Wallach Measure with respect to the the Haar Value(The average entanglement of Pseudo Random states $\\langle \\mathcal{Q}_R \\rangle$).\n",
    " 3. The Meyer-Wallach Measure gives us the global entanglement over the entire statevector. The average over the Parametric Quantum Circuit gives use the measure of the circuit give a quantification of the toal type and number of entangles states a particular circuit can generate.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "def compute_ptrace(ket: np.ndarray, num_qubits: int) -> float:\n",
    "    \"\"\"Return the values of entanglement capability using meyer-wallach measure.\n",
    "    Args:\n",
    "        ket : (numpy.ndarray or list);Vector of amplitudes in 2**N dimensions\n",
    "        num_qubits : (int)Number of qubits\n",
    "\n",
    "    Returns:\n",
    "        q: float; Q value for input ket\n",
    "    \"\"\"\n",
    "    \n",
    "\n",
    "    entanglement_sum = 0\n",
    "    for k in range(num_qubits):\n",
    "\n",
    "        trace_over = [q for q in range(num_qubits) if q != k]\n",
    "        rho_k = partial_trace(ket, trace_over).data\n",
    "        entanglement_sum += np.real((np.linalg.matrix_power(rho_k, 2)).trace())\n",
    "\n",
    "    q = 2 * (1 - (1 / num_qubits) * entanglement_sum)\n",
    "\n",
    "    return q\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The following cell implements entangling capacity using Von-Neumann entropy measure. It expects as input the statevector of $n$ qubits and the total number of qubits $n$ for calculating the the entangling capacity of a particular statevector using Von-Neumann Measure.\n",
    "Von-Neumann Measure measure (this measure is also know as Von-Neumann Shanon Entropy) and is defined by \n",
    "$\n",
    "\\begin{equation}\n",
    "    \\mathcal{Q}(|\\psi\\rangle) = -\\sum_{i=1}^{n}Tr\\{\\rho_i log_e (\\rho_i)\\}\n",
    "\\end{equation}\n",
    "$\n",
    "The Von-Neumann Measure find its application in quantum information processing due to following advantages:\n",
    "1. It gives the  local entanglement measure of each qubit by taking the partial trace of reduce density matric given an average over the entanglement capability over the different qubits in a particular statevector.\n",
    "2. This measure give different measure for different kinds of entanglement for e.g. $|\\psi\\rangle = \\frac{|00\\rangle_{1,2}+|11\\rangle_{1,2}}{\\sqrt{2}}\\otimes\\frac{|00\\rangle_{3,4}+|11\\rangle_{3,4}}{\\sqrt{2}}$ and the four qubit $GHZ$ state, the four qubit GHZ state give us a higher entanglement measure in the von-neumann measure as compared to Meyer-Wallach measure(which give 1 for both the states.). Hence, it is better able to distinguish between the different kinds of entanglement.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "def compute_vn_entropy(ket: np.ndarray, num_qubits: int) -> float:\n",
    "    \"\"\"Returns the entangling capabilility using von-neumann entropy.\n",
    "    Args:\n",
    "        ket : (numpy.ndarray or list);Vector of amplitudes in 2**N dimensions\n",
    "        num_qubits : (int)Number of qubits\n",
    "\n",
    "    Returns:\n",
    "        q: float; Q value for input ket\n",
    "    \"\"\"\n",
    "\n",
    "\n",
    "    qubit = list(range(num_qubits))  # list of qubits to trace over\n",
    "\n",
    "    vn_entropy = 0\n",
    "\n",
    "    for k in range(num_qubits):\n",
    "        rho_k = qi.partial_trace(ket, qubit[:k] + qubit[k + 1 :]).data\n",
    "        vn_entropy += qi.entropy(rho_k, base=np.exp(1))\n",
    "    q = vn_entropy / num_qubits\n",
    "    return q"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The following cells computes entanglement capacity given a parametric circuit, using Meyer Wallach Measure by sampling over different parameter values of the parametric quantum gates to give us an average measure of the Meyer Wallach measure we can expect from a particular parametric quantum circuit.\n",
    "The function takes as input the total no. of parameters which is also the number of samples , the parametric circuit whose entanglement measure we want to calculate and the backend which we want to use.\n",
    "Note: We can only use statevector backend to calculate the Entanglement measures."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "def meyer_wallach(num_params, feature_dim, layers, circuit_id) -> float:\n",
    "        \"\"\"\n",
    "        Returns:\n",
    "                net_entanglement_cap: The meyer-wallach entangling capacity of the\n",
    "                                       given parametric circuit.\n",
    "        \"\"\"\n",
    "\n",
    "        entanglement_cap = []\n",
    "\n",
    "        for _ in range(num_params):\n",
    "            \n",
    "            parametric_circuit = Ansatz(layers + 1, feature_dim, circuit_id).get_ansatz()\n",
    "            state_vector = Statevector(parametric_circuit)\n",
    "            state_vector = np.array(state_vector)\n",
    "            q_value = compute_ptrace(ket=state_vector, num_qubits=feature_dim)\n",
    "            entanglement_cap.append(q_value)\n",
    "\n",
    "        entanglement_cap = np.array(entanglement_cap)\n",
    "        net_entanglement_cap = np.sum(entanglement_cap) / num_params\n",
    "\n",
    "        return net_entanglement_cap"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The following cells computes entanglement capacity given a parametric circuit, using Von-Neumann Measure by sampling over different parameter values of the parametric quantum gates to give us an average measure of the Von-Neumann measure we can expect from a particular parametric quantum circuit.\n",
    "The function takes as input the total no. of parameters which is also the number of samples , the parametric circuit whose entanglement measure we want to calculate and the backend which we want to use.\n",
    "Note: We can only use statevector backend to calculate the Entanglement measures."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [],
   "source": [
    "def von_neumann(num_params,  feature_dim, layers, circuit_id) -> float:\n",
    "\n",
    "        \"\"\"\n",
    "        Returns:\n",
    "              net_entanglement_cap: The von_neumann entangling capacity of the given parametric circuit.\n",
    "        \"\"\"\n",
    "\n",
    "        entanglement_cap = []\n",
    "\n",
    "        for _ in range(num_params):\n",
    "\n",
    "            parametric_circuit = Ansatz(layers + 1, feature_dim, circuit_id).get_ansatz()\n",
    "            state_vector = Statevector(parametric_circuit).data\n",
    "            state_vector = np.array(state_vector)\n",
    "            q_value = compute_vn_entropy(ket=state_vector, num_qubits=feature_dim)\n",
    "            entanglement_cap.append(q_value)\n",
    "\n",
    "        entanglement_cap = np.array(entanglement_cap)\n",
    "        net_entanglement_cap = np.sum(entanglement_cap) / num_params\n",
    "\n",
    "        return net_entanglement_cap"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In order to be able to reproduce the results of the paper [1], we provide an additional code ansatz.py which has the 19 parameterized quantum circuits given in the paper. The following cell calculates the entanglinhg capacity of all the 19 circuits. \n",
    "circuit_id can be used if a particular ansatz from the benchmarked ansatz is required. else we can do it for all ansatzes of that code.\n",
    "\n",
    "feature dim: refers to the number of features in the input data. this is important to know as this determines the number of qubits in the circuit for Z and ZZ feature map. \n",
    "\n",
    "repetition: refers to the number of layers of ansatz required. Note: deeper ansatz get more noisy and circuit depth impacts results.\n",
    "\n",
    "num_eval: refers to the number of runs needed for the circuits. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from parametric_circuits import Ansatz\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "\n",
    "\n",
    "total_circuit = 10\n",
    "feature_dim = 4\n",
    "repitition = 5\n",
    "entanglement_cap = np.zeros((total_circuit, repitition))\n",
    "\n",
    "\n",
    "for i in range(total_circuit):\n",
    "    circuit_id = i + 1\n",
    "\n",
    "    for layers in range(repitition):\n",
    "\n",
    "        \n",
    "        ent_cap = meyer_wallach(num_params = 100, feature_dim = feature_dim, layers = layers, circuit_id = circuit_id)\n",
    "        entanglement_cap[i, layers] = ent_cap\n",
    "\n",
    "index = [\"Ansatz \"+str(i+1) for i in range(total_circuit)]\n",
    "df = pd.DataFrame({'Layer1':entanglement_cap[:,0], \"Layer2\":entanglement_cap[:,1], \"Layer3\":entanglement_cap[:,2],\n",
    "                   \"Layer4\":entanglement_cap[:,3],\"Layer5\":entanglement_cap[:,4]}, index = index)\n",
    "file_name = \"entropy_run_5_Layers\" \n",
    "df.to_csv(file_name + \".csv\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Unnamed: 0</th>\n",
       "      <th>Layer1</th>\n",
       "      <th>Layer2</th>\n",
       "      <th>Layer3</th>\n",
       "      <th>Layer4</th>\n",
       "      <th>Layer5</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Ansatz 1</td>\n",
       "      <td>1.132427e-16</td>\n",
       "      <td>-4.218847e-17</td>\n",
       "      <td>-4.329870e-16</td>\n",
       "      <td>-6.172840e-16</td>\n",
       "      <td>-5.995204e-17</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Ansatz 2</td>\n",
       "      <td>5.401581e-01</td>\n",
       "      <td>5.556001e-01</td>\n",
       "      <td>6.900341e-01</td>\n",
       "      <td>6.438951e-01</td>\n",
       "      <td>6.726030e-01</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Ansatz 3</td>\n",
       "      <td>4.720906e-02</td>\n",
       "      <td>1.204134e-01</td>\n",
       "      <td>1.817087e-01</td>\n",
       "      <td>2.231124e-01</td>\n",
       "      <td>2.382670e-01</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>Ansatz 4</td>\n",
       "      <td>8.341888e-02</td>\n",
       "      <td>1.888078e-01</td>\n",
       "      <td>3.073650e-01</td>\n",
       "      <td>3.397621e-01</td>\n",
       "      <td>3.802105e-01</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>Ansatz 5</td>\n",
       "      <td>2.223875e-01</td>\n",
       "      <td>3.931126e-01</td>\n",
       "      <td>4.454848e-01</td>\n",
       "      <td>4.625990e-01</td>\n",
       "      <td>4.391473e-01</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>Ansatz 6</td>\n",
       "      <td>2.530011e-01</td>\n",
       "      <td>4.370052e-01</td>\n",
       "      <td>4.661679e-01</td>\n",
       "      <td>5.276274e-01</td>\n",
       "      <td>5.585503e-01</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>Ansatz 7</td>\n",
       "      <td>7.516283e-02</td>\n",
       "      <td>1.609968e-01</td>\n",
       "      <td>2.594939e-01</td>\n",
       "      <td>3.152684e-01</td>\n",
       "      <td>3.666315e-01</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>Ansatz 8</td>\n",
       "      <td>8.999807e-02</td>\n",
       "      <td>2.076772e-01</td>\n",
       "      <td>2.773615e-01</td>\n",
       "      <td>3.431136e-01</td>\n",
       "      <td>4.149008e-01</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>Ansatz 9</td>\n",
       "      <td>1.000000e+00</td>\n",
       "      <td>1.000000e+00</td>\n",
       "      <td>1.000000e+00</td>\n",
       "      <td>5.924633e-01</td>\n",
       "      <td>6.888367e-01</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>Ansatz 10</td>\n",
       "      <td>3.865358e-01</td>\n",
       "      <td>6.801451e-01</td>\n",
       "      <td>8.198149e-01</td>\n",
       "      <td>7.264927e-01</td>\n",
       "      <td>7.441896e-01</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  Unnamed: 0        Layer1        Layer2        Layer3        Layer4  \\\n",
       "0   Ansatz 1  1.132427e-16 -4.218847e-17 -4.329870e-16 -6.172840e-16   \n",
       "1   Ansatz 2  5.401581e-01  5.556001e-01  6.900341e-01  6.438951e-01   \n",
       "2   Ansatz 3  4.720906e-02  1.204134e-01  1.817087e-01  2.231124e-01   \n",
       "3   Ansatz 4  8.341888e-02  1.888078e-01  3.073650e-01  3.397621e-01   \n",
       "4   Ansatz 5  2.223875e-01  3.931126e-01  4.454848e-01  4.625990e-01   \n",
       "5   Ansatz 6  2.530011e-01  4.370052e-01  4.661679e-01  5.276274e-01   \n",
       "6   Ansatz 7  7.516283e-02  1.609968e-01  2.594939e-01  3.152684e-01   \n",
       "7   Ansatz 8  8.999807e-02  2.076772e-01  2.773615e-01  3.431136e-01   \n",
       "8   Ansatz 9  1.000000e+00  1.000000e+00  1.000000e+00  5.924633e-01   \n",
       "9  Ansatz 10  3.865358e-01  6.801451e-01  8.198149e-01  7.264927e-01   \n",
       "\n",
       "         Layer5  \n",
       "0 -5.995204e-17  \n",
       "1  6.726030e-01  \n",
       "2  2.382670e-01  \n",
       "3  3.802105e-01  \n",
       "4  4.391473e-01  \n",
       "5  5.585503e-01  \n",
       "6  3.666315e-01  \n",
       "7  4.149008e-01  \n",
       "8  6.888367e-01  \n",
       "9  7.441896e-01  "
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df = pd.read_csv('entropy_run_5_Layers.csv')\n",
    "df"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "to Plot Entangling Capacity of all 10 circuits across 5 layers. Observe how entangling capacity increases with increasing the mumber of layers which is intuitive as the number of entangling gates also increase"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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T+en2148akfAjjvuuH3bVEyFvfuR5XI5zjjjDL785S+Ty+WO+Oe6Y74kSVJVjJGRkZH9+i6++GKeffZZnnzySQYHB/nqV79ak3MZwiRJUqoqFejtTdpa2r59O8uXL2fx4sUsWLCANWvWAHDDDTdwyy237Dvu+uuv59ZbbwXgpptuYunSpSxcuJAbb7wRSO4dedppp3HppZcyf/58Xnjhhf3O8wd/8AeEEAghcMYZZ7B169aa1G8IkyRJqenpgc5OWLEiaXt6avez29rauPfee3nsscdYv34911xzDTFGVq1axR13JDfsGRkZ4e677+aSSy5h3bp19PX18cgjj/DEE0+wadMmNm7cCEBfXx9XXXUVTz/9NJ2dnQc839DQEN/4xjd4z3veU5P662KfMEmSVH8qFSgWYXAw+YLkcVcX5GuweX6Mkeuuu46NGzcybdo0tm3bxksvvUShUGDWrFk8/vjjvPTSSyxatIhZs2axbt061q1bt28bie3bt9PX18fJJ59MZ2cnZ5111rjnu+qqq/jd3/1dfud3fufIi8cQJkmSUlIuQ2vrvwUwgFwu6a9FCLvrrruoVCps2rSJXC5HoVBg165dAFx++eXcfvvtvPjii6xatQpIQtu1117LlVdeOabOMh0dHeOe6zOf+QyVSoUvf/nLR154ldORkiQpFYUC7N69f9/QUNJfCwMDA5xwwgnkcjnWr19Pf3//vucuvPBC7r//fnp7e1m5ciUAK1eu5Lbbbtv3ycpt27bx8ssvH/I8X/3qV/ne975HT08P06bVLjo5EiZJklKRz0OplExB5nJJACuVajMKBsmnFs877zwWLFjAkiVLOP30f9tSo7W1lXPOOYeZM2fS0tICwLnnnsszzzzD2WefDSRbXdx55537nj+YP/qjP6Kzs3Pf697//vdzww03HHH9hjBJkpSa7u5kDVi5nIyA1SKA7R3JOv7443nwwQcPeMzIyAgPPfQQ99xzz379q1evZvXq1W84/qmnnjro+fbs2XME1R6c05GSJClV+TwsXVq7EbBD2bx5M6eccgrLly9n7ty5U3PSw+BImCRJaijz5s3j+eefz7qMQ3IkTJIkKQOGMEmSpAwYwiRJkjJgCJMkScqAIUySJNWV4447bkrPVywWecc73sHChQu56KKL9m2RcaQMYZIkSVUxRkZGRvbr++u//mt++MMf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\n",
      "text/plain": [
       "<Figure size 720x576 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# import seaborn as sns\n",
    "ax = plt.gca()\n",
    "color = ['green', 'blue', 'orange', 'red', 'yellow']\n",
    "for i in range(5):\n",
    "    df.reset_index().plot.scatter(x = 'index', y = 'Layer'+str(i+1), color = color[i],marker = 'o', label = 'layer '+str(i+1), figsize = (10,8), grid = True, ax = ax)\n",
    "\n",
    "ax.set_xlabel('Circuit Id')\n",
    "ax.set_ylabel('Meyer-Wallach Measure')\n",
    "plt.show()\n",
    "\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.8"
  },
  "vscode": {
   "interpreter": {
    "hash": "7d3b8b0b17a73b27c675ad731f7f973f58a06bce747a783740f7b6d647f60952"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
